package com.devnn.baseNet;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.devnn.dao.NameValue;
import com.squareup.okhttp.Response;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by devnn on 16/1/18.
 */
public abstract class BaseDAO implements Runnable, Handler.Callback {
    public String TAG = this.getClass().getSimpleName();
    private String host = "http://app.kuaiditu.com";
    private String baseApi = "/kuaidituCourierApi/v1/";

    private String ralUrl;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getBaseApi() {
        return baseApi;
    }

    public void setBaseApi(String baseApi) {
        this.baseApi = baseApi;
    }

    private RequestListener requestListener;

    private BaseRequest baseRequest;

    private String requestParams;

    public static final int ERROR_CODE_NONET = 10;
    public static final int ERROR_CODE_NONE = 11;
    public static final int ERROR_CODE_IO = 12;
    public static final int ERROR_CODE_JSON_PARSE = 13;
    public static final int ERROR_CODE_RESPONSE_FALSE = 14;
    public int errorCode;
    public String errorMessage;
    private Handler handler = new Handler(this);
    private String responseString;

    public interface RequestListener {
        void onRequestSucceed(BaseDAO baseDAO);

        void onRequestFailed(BaseDAO baseDAO);
    }

    public void setRequestListener(RequestListener requestListener) {
        this.requestListener = requestListener;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public int getErrorCode() {
        return errorCode;
    }

    public void request(Map<String, Object> params) {
        params.put("timestamp", new Date().getTime());
        this.requestParams = JSON.toJSONString(params);
        Log.i(TAG, "request api:" + this.getHost() + this.baseApi + getActionName());
        Log.i(TAG, "request params:" + requestParams);
        load();
    }

    public void request(List<NameValue> params) {
        params.add(new NameValue("timestamp", new Date().getTime()));
        this.requestParams = JSON.toJSONString(params);
        Log.i(TAG, "request api:" + this.getHost() + this.baseApi + getActionName());
        Log.i(TAG, "request params:" + requestParams);
        load();
    }

    public void request(NameValue... params) {
        List<NameValue> listParams = new ArrayList<NameValue>();
        for (NameValue nameValue : params) {
            listParams.add(nameValue);
        }
        listParams.add(new NameValue("timestamp", new Date().getTime()));
        this.requestParams = JSON.toJSONString(params);
        Log.i(TAG, "request api:" + this.getHost() + this.baseApi + getActionName());
        Log.i(TAG, "request params:" + requestParams);
        load();
    }

    private void load() {
        Thread thread = new Thread(this);
        thread.start();
    }

    public abstract String getActionName();

    public abstract void parseJSONResult(JSONObject jsonResponse);


    private void loadSuccess() {
        if (requestListener != null) {
            requestListener.onRequestSucceed(this);
        }
    }

    private void loadFailed() {
        Log.e(TAG,"error code:"+errorCode);
        Log.e(TAG,"error message:"+errorMessage);
        if (requestListener != null) {
            requestListener.onRequestFailed(this);
        }
    }

    private void checkJSONError(String responseString) {
        JSONObject jsonObject;
        try {
            jsonObject = new JSONObject(responseString);
        } catch (JSONException e) {
            e.printStackTrace();
            errorCode = ERROR_CODE_JSON_PARSE;
            errorMessage = "response is not json string";
            loadFailed();
            return;
        }
        if (jsonObject.has("success") && jsonObject.has("result") && jsonObject.has("message")) {
            if (jsonObject.optBoolean("success")) {
                try {
                    parseJSONResult(jsonObject);
                    errorCode = ERROR_CODE_NONE;
                    errorMessage = jsonObject.optString("message");
                    loadSuccess();
                } catch (Exception e) {
                    e.printStackTrace();
                    errorCode = ERROR_CODE_JSON_PARSE;
                    errorMessage = "parse success data error";
                    loadFailed();
                }

            } else {
                errorCode = ERROR_CODE_RESPONSE_FALSE;
                errorMessage = jsonObject.optString("message");
                try {
                    parseJSONResult(jsonObject);
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, "解析false数据出错");
                }
                loadFailed();
            }
        } else {
            errorCode = ERROR_CODE_JSON_PARSE;
            errorMessage = "response json is not the specifed structure";
            loadFailed();
        }
    }


    @Override
    public void run() {
        baseRequest = new BaseRequest();
        Response response = baseRequest.doPost(this.host + this.baseApi + getActionName(), this.requestParams);
        Message msg = new Message();
        if (response == null) {
            msg.what = ERROR_CODE_NONET;
        } else {
            try {
                Log.i(TAG,"http code:"+response.code());
                responseString = response.body().string();
                Log.i(TAG, "response string:" + responseString);
                msg.what = response.code();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(TAG, "response_read_error:" + e.getMessage());
                msg.what = ERROR_CODE_IO;
            }
        }
        handler.sendMessage(msg);
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == ERROR_CODE_NONET) {
            errorCode = ERROR_CODE_NONET;
            errorMessage = "网络不可用";
            loadFailed();
        } else if (msg.what == ERROR_CODE_IO) {
            errorCode = ERROR_CODE_IO;
            errorMessage = "steam read exceptipn";
            loadFailed();
        } else if (msg.what == 200) {
            checkJSONError(responseString);
        } else if (msg.what == 404) {
            errorCode = msg.what;
            errorMessage = "服务器接口不存在";
            loadFailed();
        } else {
            errorCode = msg.what;
            errorMessage = "服务器内部出错";
            loadFailed();
        }
        return false;
    }
}
